import 'dart:async';

import 'package:built_collection/built_collection.dart';
import 'package:equatable/equatable.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/app_navigator_transition_info.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/learning_content/lexical_item/lexical_item.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/page_models/app_navigator_page_model.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/page_models/single_word_base_page_model.dart';
import 'package:learning_content_admin_pannel.core/core/domain/helpers/handle_root_navigator_page_closing_request/use_case.dart';
import 'package:learning_content_admin_pannel.core/core/domain/helpers/handle_root_navigator_page_push_replacement_request/use_case.dart';
import 'package:learning_content_admin_pannel.core/core/domain/repositories/learning_content_repository/repository.dart';
import 'package:learning_content_admin_pannel.home.words/single_word_base_page/domain/entities/word_base_input.dart';
import 'package:learning_content_admin_pannel.home.words/single_word_base_page/domain/helpers/update_word_from_word_base_input/helper.dart';

part 'result.dart';

abstract class HandlePreviousWordBasePageOpeningRequest {
  PreviousWordBasePageOpeningRequestHandlingResult call({
    required SingleWordBasePageModel pageModel,
    required WordBaseInput wordBaseInput,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required BuiltList<AppNavigatorPageModel> rootNavigatorPageModels,
    required BuiltMap<AppNavigatorPageModel, AppNavigatorTransitionInfo>
        rootNavigatorPageModelToTransitionInfo,
  });
}

class HandlePreviousWordBasePageOpeningRequestImpl
    implements HandlePreviousWordBasePageOpeningRequest {
  const HandlePreviousWordBasePageOpeningRequestImpl({
    required HandleRootNavigatorPageClosingRequest handleRootNavigatorPageClosingRequest,
    required HandleRootNavigatorPagePushReplacementRequest
        handleRootNavigatorPagePushReplacementRequest,
    required UpdateWordFromWordBaseInput updateWordFromWordBaseInput,
    required LearningContentRepository learningContentRepository,
  })  : _handleRootNavigatorPageClosingRequest = handleRootNavigatorPageClosingRequest,
        _handleRootNavigatorPagePushReplacementRequest =
            handleRootNavigatorPagePushReplacementRequest,
        _updateWordFromWordBaseInput = updateWordFromWordBaseInput,
        _learningContentRepository = learningContentRepository;

  final HandleRootNavigatorPageClosingRequest _handleRootNavigatorPageClosingRequest;
  final HandleRootNavigatorPagePushReplacementRequest
      _handleRootNavigatorPagePushReplacementRequest;
  final UpdateWordFromWordBaseInput _updateWordFromWordBaseInput;
  final LearningContentRepository _learningContentRepository;

  @override
  PreviousWordBasePageOpeningRequestHandlingResult call({
    required SingleWordBasePageModel pageModel,
    required WordBaseInput wordBaseInput,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required BuiltList<AppNavigatorPageModel> rootNavigatorPageModels,
    required BuiltMap<AppNavigatorPageModel, AppNavigatorTransitionInfo>
        rootNavigatorPageModelToTransitionInfo,
  }) {
    final word = lexicalItemMap[pageModel.wordId] as Word;

    final updatedWord = _updateWordFromWordBaseInput(
      word: word,
      wordBaseInput: wordBaseInput,
    );

    final updatedLexicalItemMap = lexicalItemMap.rebuild((lexicalItemMap) {
      lexicalItemMap[updatedWord.id] = updatedWord;
    });

    final existingWordIds = pageModel.wordIds.where((wordId) {
      return lexicalItemMap.containsKey(wordId);
    }).toList();

    final wordIndex = existingWordIds.indexOf(pageModel.wordId);

    final BuiltList<AppNavigatorPageModel> updatedRootNavigatorPageModels;
    final BuiltMap<AppNavigatorPageModel, AppNavigatorTransitionInfo>
        updatedRootNavigatorPageModelToTransitionInfo;

    if (wordIndex > 0) {
      final previousWordId = existingWordIds[wordIndex - 1];

      final previousWordBasePageModel = SingleWordBasePageModel(
        wordId: previousWordId,
        wordIds: pageModel.wordIds,
      );

      final rootNavigatorPagePushHandlingResult = _handleRootNavigatorPagePushReplacementRequest(
        pageModel: previousWordBasePageModel,
        rootNavigatorPageModels: rootNavigatorPageModels,
        rootNavigatorPageModelToTransitionInfo: rootNavigatorPageModelToTransitionInfo,
      );

      updatedRootNavigatorPageModels = rootNavigatorPagePushHandlingResult.rootNavigatorPageModels;
      updatedRootNavigatorPageModelToTransitionInfo =
          rootNavigatorPagePushHandlingResult.rootNavigatorPageModelToTransitionInfo;
    } else {
      final rootNavigatorPageClosingResult = _handleRootNavigatorPageClosingRequest(
        pageModel: pageModel,
        rootNavigatorPageModels: rootNavigatorPageModels,
        rootNavigatorPageModelToTransitionInfo: rootNavigatorPageModelToTransitionInfo,
      );

      updatedRootNavigatorPageModels = rootNavigatorPageClosingResult.rootNavigatorPageModels;
      updatedRootNavigatorPageModelToTransitionInfo =
          rootNavigatorPageClosingResult.rootNavigatorPageModelToTransitionInfo;
    }

    unawaited(_learningContentRepository.saveLexicalItems(
      lexicalItems: updatedLexicalItemMap.values.toBuiltList(),
    ));

    final result = PreviousWordBasePageOpeningRequestHandlingResult(
      lexicalItemMap: updatedLexicalItemMap,
      rootNavigatorPageModels: updatedRootNavigatorPageModels,
      rootNavigatorPageModelToTransitionInfo: updatedRootNavigatorPageModelToTransitionInfo,
    );

    return result;
  }
}
